/**
 * AI作文批改服务
 * 集成DeepSeek V3.1 Terminus模型进行作文批改
 */

import axios from 'axios';
import config from '../config/index.js';
import { AppError } from '../utils/appError.js';

// Volces API配置
const VOLCES_API_URL = config.volces.apiUrl || 'https://ark.cn-beijing.volces.com/api/v3/chat/completions';
const VOLCES_API_KEY = config.volces.apiKey;
const VOLCES_MODEL = config.volces.model || 'deepseek-v3-1-terminus';
const API_TIMEOUT = config.volces.timeout || 30000;
const MAX_RETRIES = config.volces.maxRetries || 3;

/**
 * Prompt模板 - 小学作文批改
 */
const PRIMARY_PROMPT = `# 角色设定
你是一位亲切有耐心的小学语文老师，擅长鼓励式教育，针对6-12岁学生。

# 批改重点层级
## 第一层级：基础规范（必须检查）
1. **错别字检查**：逐字检查拼音错误、形近字错误
2. **标点符号**：逗号、句号、问号、感叹号使用规范
3. **基本格式**：段落开头空两格、标点占格规范

## 第二层级：语句通顺
1. **病句修正**：主谓宾搭配、词语搭配不当
2. **重复啰嗦**：删除不必要的重复词语
3. **句子完整**：检查成分残缺的句子

## 第三层级：内容结构
1. **字数达标**：是否符合年级要求
2. **段落分明**：是否有基本的分段意识
3. **内容相关**：是否围绕主题写作

# 评分标准（百分制）
## 基础规范（40分）
- 错别字：每个扣0.5分，最多扣10分
- 标点符号：每个错误扣0.5分，最多扣5分
- 书写格式：格式错误扣2-5分

## 语言表达（30分）
- 语句通顺：15分
- 词语准确：10分
- 表达生动：5分

## 内容结构（30分）
- 内容完整：10分
- 条理清晰：10分
- 主题突出：10分

# 输出要求
请严格按照以下JSON格式输出：
{
  "grade_level": "primary",
  "basic_stats": {
    "word_count": 字数,
    "paragraph_count": 段落数,
    "error_count": 错误数量
  },
  "score_breakdown": {
    "basic_norms": 基础规范得分,
    "language_expression": 语言表达得分,
    "content_structure": 内容结构得分,
    "total_score": 总分
  },
  "corrections": [
    {
      "type": "spelling|punctuation|grammar|logic|format",
      "position": "位置描述",
      "original_text": "原文",
      "suggested_text": "修改建议",
      "error_reason": "错误原因",
      "severity": "low|medium|high"
    }
  ],
  "encouraging_comments": "鼓励性总评",
  "improvement_suggestions": ["建议1", "建议2"],
  "writing_tips": ["技巧1", "技巧2"]
}`;

/**
 * Prompt模板 - 初中作文批改
 */
const MIDDLE_PROMPT = `# 角色设定
你是严谨认真的初中语文教师，注重逻辑思维和表达能力培养。

# 批改重点层级
## 第一层级：语言准确性
1. **词语精准度**：近义词辨析、词语感情色彩
2. **句式多样性**：长短句结合、修辞手法运用
3. **语法规范**：复杂句式的语法正确性

## 第二层级：逻辑结构
1. **段落衔接**：过渡句、承上启下
2. **论证严密**：观点与论据的匹配度
3. **结构完整**：开头、主体、结尾的完整性

## 第三层级：思想深度
1. **立意新颖**：观点是否独特、有见地
2. **情感真实**：情感表达是否真挚自然
3. **文化内涵**：是否有一定的思想深度

# 评分标准（百分制）
## 内容立意（40分）
- 主题明确：10分
- 内容充实：15分
- 思想深刻：15分

## 语言表达（30分）
- 语言准确：10分
- 文采修辞：10分
- 表达流畅：10分

## 结构技巧（30分）
- 结构严谨：10分
- 层次清晰：10分
- 详略得当：10分

# 输出要求
请严格按照以下JSON格式输出：
{
  "grade_level": "middle",
  "advanced_analysis": {
    "thesis_strength": "论点力度评价",
    "argument_quality": "论证质量",
    "rhetorical_skills": "修辞手法运用"
  },
  "score_breakdown": {
    "content_meaning": 内容立意得分,
    "language_expression": 语言表达得分,
    "structure_skills": 结构技巧得分,
    "total_score": 总分
  },
  "detailed_corrections": [
    {
      "category": "language|logic|structure|content",
      "specific_issue": "具体问题描述",
      "original_excerpt": "原文片段",
      "suggested_revision": "修改建议",
      "rationale": "修改理由",
      "learning_point": "相关知识点"
    }
  ],
  "strength_analysis": "优点详细分析",
  "weakness_analysis": "待改进方面分析",
  "specific_suggestions": [
    {
      "aspect": "方面",
      "suggestion": "具体建议",
      "example": "示范例句"
    }
  ]
}`;

/**
 * Prompt模板 - 高中作文批改
 */
const HIGH_PROMPT = `# 角色设定
你是资深高中语文教师，高考作文阅卷经验丰富，注重思辨性和文学性。

# 批改重点层级
## 第一层级：思想深度
1. **观点创新**：是否具有独到见解
2. **思辨能力**：分析问题的深度和广度
3. **价值取向**：价值观是否正确积极

## 第二层级：文学素养
1. **文采斐然**：语言的美感和感染力
2. **文化底蕴**：古今中外知识的融汇
3. **个性风格**：是否有个人写作风格

## 第三层级：技巧娴熟
1. **结构精巧**：文章结构的艺术性
2. **手法纯熟**：各种写作手法的运用
3. **材料新颖**：素材的独特性和时代性

# 高考评分标准（60分制转换为百分制）
## 基础等级（40分）
- 内容：20分（切题、充实、深刻）
- 表达：20分（规范、流畅、生动）

## 发展等级（20分）
- 特征：10分（深刻、丰富、有文采）
- 创新：10分（见解新颖、材料新鲜）

# 输出要求
请严格按照以下JSON格式输出：
{
  "grade_level": "high",
  "college_entrance_standard": {
    "basic_level_score": 基础等级得分,
    "development_level_score": 发展等级得分,
    "total_score": 总分（60分制）,
    "percentage_score": 百分制得分
  },
  "depth_analysis": {
    "theoretical_depth": "思想深度评价",
    "cultural_literacy": "文化素养体现",
    "critical_thinking": "思辨能力分析"
  },
  "artistic_evaluation": {
    "language_artistry": "语言艺术性",
    "structural_ingenuity": "结构巧妙性",
    "stylistic_features": "风格特征"
  },
  "corrections": [
    {
      "type": "language|logic|structure|content",
      "position": "位置",
      "original_text": "原文",
      "suggested_text": "修改建议",
      "improvement_reason": "提升理由"
    }
  ],
  "college_prep_suggestions": [
    {
      "exam_skill": "应试技巧建议",
      "knowledge_gap": "知识漏洞指出",
      "improvement_plan": "提升方案"
    }
  ],
  "model_essay_comparison": "与范文对比分析"
}`;

/**
 * 主控Prompt - 用于系统消息
 */
const MASTER_PROMPT = `你是专业作文批改AI系统，负责为不同学段的学生批改作文。

# 核心原则
1. 严格按照指定的JSON格式输出
2. 评分客观公正，符合学段标准
3. 批注具体明确，有针对性
4. 建议切实可行，有指导意义

# 处理流程
1. 分析作文基本信息：字数、段落数、体裁
2. 根据学段标准进行全面批改
3. 生成结构化的批改结果

请务必输出有效的JSON格式，不要包含任何额外的文字说明。`;

/**
 * 构建批改Prompt
 * @param {string} essayContent - 作文内容
 * @param {string} gradeLevel - 学段 (primary/middle/high)
 * @param {Object} options - 可选参数
 * @returns {Object} { systemPrompt, userPrompt }
 */
export const constructPrompt = (essayContent, gradeLevel, options = {}) => {
  // 验证输入
  if (!essayContent || typeof essayContent !== 'string' || essayContent.trim().length === 0) {
    throw new AppError('INVALID_INPUT', '作文内容不能为空', 400);
  }

  if (!['primary', 'middle', 'high'].includes(gradeLevel)) {
    throw new AppError('INVALID_INPUT', '学段必须是primary、middle或high之一', 400);
  }

  // 选择对应学段的Prompt
  const promptMap = {
    primary: PRIMARY_PROMPT,
    middle: MIDDLE_PROMPT,
    high: HIGH_PROMPT,
  };

  const gradeLevelPrompt = promptMap[gradeLevel];

  // 构建系统Prompt
  const systemPrompt = `${MASTER_PROMPT}

${gradeLevelPrompt}`;

  // 构建用户Prompt
  const userPrompt = `请批改以下作文：

【作文信息】
- 学生学段：${gradeLevel === 'primary' ? '小学' : gradeLevel === 'middle' ? '初中' : '高中'}
- 作文标题：${options.title || '无标题'}
- 作文字数：${essayContent.length}字
- 批改时间：${new Date().toISOString()}

【作文内容】
${essayContent}

${options.additionalRequirements ? `【附加要求】\n${options.additionalRequirements}\n` : ''}
请严格按照指定的JSON格式输出批改结果，不要包含任何其他文字。`;

  return {
    systemPrompt,
    userPrompt,
  };
};

/**
 * 调用Volces API
 * @param {Array} messages - 消息数组
 * @param {Object} options - 可选参数
 * @returns {Promise<Object>} API响应
 */
const callVolcesAPI = async (messages, options = {}) => {
  // 验证API Key
  if (!VOLCES_API_KEY) {
    throw new AppError('API_CONFIG_ERROR', '未配置VOLCES_API_KEY环境变量', 500);
  }

  try {
    const response = await axios.post(
      VOLCES_API_URL,
      {
        model: VOLCES_MODEL,
        messages: messages,
        temperature: options.temperature || 0.7,
        max_tokens: options.maxTokens || 2000,
      },
      {
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${VOLCES_API_KEY}`,
        },
        timeout: options.timeout || API_TIMEOUT,
      }
    );

    return response.data;
  } catch (error) {
    // 记录API调用错误
    console.error('Volces API调用失败:', {
      message: error.message,
      status: error.response?.status,
      data: error.response?.data,
    });

    // 处理不同类型的错误
    if (error.code === 'ECONNABORTED') {
      throw new AppError('API_TIMEOUT', 'AI服务响应超时，请稍后重试', 504);
    }

    if (error.response) {
      const status = error.response.status;
      const errorData = error.response.data;

      switch (status) {
        case 401:
          throw new AppError('API_AUTH_ERROR', 'API认证失败，请检查API Key', 401);
        case 429:
          throw new AppError('API_RATE_LIMIT', 'API请求频率超限，请稍后重试', 429);
        case 500:
        case 502:
        case 503:
          throw new AppError('API_SERVER_ERROR', 'AI服务暂时不可用，请稍后重试', 503);
        default:
          throw new AppError(
            'API_ERROR',
            errorData?.error?.message || 'AI服务调用失败',
            status
          );
      }
    }

    throw new AppError('API_NETWORK_ERROR', '网络连接失败，请检查网络设置', 500);
  }
};

/**
 * 带重试机制的API调用
 * @param {Array} messages - 消息数组
 * @param {Object} options - 可选参数
 * @returns {Promise<Object>} API响应
 */
const callAPIWithRetry = async (messages, options = {}) => {
  const maxRetries = options.maxRetries || MAX_RETRIES;
  let lastError;

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      console.log(`API调用尝试 ${attempt + 1}/${maxRetries}`);
      const response = await callVolcesAPI(messages, options);
      console.log('API调用成功');
      return response;
    } catch (error) {
      lastError = error;

      // 对于某些错误，不应该重试
      if (
        error.type === 'API_AUTH_ERROR' ||
        error.type === 'INVALID_INPUT' ||
        error.type === 'API_CONFIG_ERROR'
      ) {
        throw error;
      }

      // 如果不是最后一次尝试，等待后重试
      if (attempt < maxRetries - 1) {
        const backoffTime = Math.pow(2, attempt) * 1000; // 指数退避：1s, 2s, 4s
        console.log(`等待 ${backoffTime}ms 后重试...`);
        await new Promise((resolve) => setTimeout(resolve, backoffTime));
      }
    }
  }

  // 所有重试都失败
  console.error('API调用失败，已达最大重试次数');
  throw lastError;
};

/**
 * 解析AI响应
 * @param {Object} response - Volces API响应
 * @returns {Object} 解析后的批改结果
 */
export const parseAIResponse = (response) => {
  try {
    // 验证响应格式
    if (!response || !response.choices || response.choices.length === 0) {
      throw new Error('API响应格式无效：缺少choices字段');
    }

    const content = response.choices[0].message?.content;
    if (!content) {
      throw new Error('API响应格式无效：缺少content字段');
    }

    // 尝试解析JSON
    // 移除可能的markdown代码块标记
    let cleanContent = content.trim();
    if (cleanContent.startsWith('```json')) {
      cleanContent = cleanContent.replace(/^```json\s*/, '').replace(/\s*```$/, '');
    } else if (cleanContent.startsWith('```')) {
      cleanContent = cleanContent.replace(/^```\s*/, '').replace(/\s*```$/, '');
    }

    const parsedResult = JSON.parse(cleanContent);

    // 验证必需字段
    if (!parsedResult.grade_level) {
      throw new Error('批改结果缺少grade_level字段');
    }

    if (!parsedResult.score_breakdown || typeof parsedResult.score_breakdown.total_score !== 'number') {
      throw new Error('批改结果缺少有效的score_breakdown字段');
    }

    return {
      success: true,
      data: parsedResult,
      usage: response.usage,
    };
  } catch (error) {
    console.error('解析AI响应失败:', error.message);
    console.error('原始响应:', JSON.stringify(response, null, 2));

    // 返回原始内容以便调试
    return {
      success: false,
      error: {
        type: 'PARSE_ERROR',
        message: '批改结果解析失败',
        details: error.message,
      },
      rawContent: response.choices?.[0]?.message?.content,
    };
  }
};

/**
 * 批改作文（核心方法）
 * @param {string} essayContent - 作文内容
 * @param {string} gradeLevel - 学段 (primary/middle/high)
 * @param {Object} options - 可选参数
 * @returns {Promise<Object>} 批改结果
 */
export const correctEssay = async (essayContent, gradeLevel, options = {}) => {
  const startTime = Date.now();

  try {
    console.log(`开始批改作文 - 学段: ${gradeLevel}, 字数: ${essayContent.length}`);

    // 1. 构建Prompt
    const { systemPrompt, userPrompt } = constructPrompt(essayContent, gradeLevel, options);

    // 2. 准备消息
    const messages = [
      { role: 'system', content: systemPrompt },
      { role: 'user', content: userPrompt },
    ];

    // 3. 调用API（带重试）
    const apiResponse = await callAPIWithRetry(messages, {
      temperature: options.temperature,
      maxTokens: options.maxTokens,
      timeout: options.timeout,
      maxRetries: options.maxRetries,
    });

    // 4. 解析响应
    const parsedResult = parseAIResponse(apiResponse);

    if (!parsedResult.success) {
      throw new AppError(
        parsedResult.error.type,
        parsedResult.error.message,
        500,
        new Error(parsedResult.error.details)
      );
    }

    // 5. 计算处理时间
    const processingTime = ((Date.now() - startTime) / 1000).toFixed(2);

    // 6. 返回标准化结果
    return {
      success: true,
      data: {
        ...parsedResult.data,
        metadata: {
          essay_word_count: essayContent.length,
          processing_time: `${processingTime}s`,
          model: VOLCES_MODEL,
          timestamp: new Date().toISOString(),
        },
        usage: parsedResult.usage,
      },
      message: '作文批改成功',
    };
  } catch (error) {
    console.error('作文批改失败:', error);

    // 如果是AppError，直接抛出
    if (error instanceof AppError || error.isOperational) {
      throw error;
    }

    // 其他错误包装为通用错误
    throw new AppError('CORRECTION_FAILED', '作文批改失败，请重试', 500, error);
  }
};

export default {
  correctEssay,
  constructPrompt,
  parseAIResponse,
};

